use std::{
    cmp::Ordering,
    collections::{HashMap, VecDeque},
    future::Future,
    pin::Pin,
    sync::{Arc, atomic::AtomicU64},
};
use tokio::{
    sync::RwLock,
    time::{Duration, interval},
};

type Task = Pin<Box<dyn Future<Output = ()> + Send>>;

struct TimingWheel {
    // 三级时间轮：秒(60) / 分(60) / 时(24)
    wheels: [RwLock<HashMap<u64, VecDeque<ScheduledTask>>>; 3],
    current_tick: Arc<AtomicU64>,
    precision: Duration,
}

struct ScheduledTask {
    execute_at: u64,
    task: Task,
    cycles: [u8; 3], // 各层剩余周期数
}

impl TimingWheel {
    pub fn new() -> Self {
        TimingWheel {
            wheels: Default::default(),
            current_tick: Arc::new(AtomicU64::new(0)),
            precision: Duration::from_secs(1),
        }
    }

    // 采用RAII模式自动管理任务生命周期
    pub async fn add_task<F>(&self, delay: Duration, f: F) -> TaskHandle
    where
        F: Future<Output = ()> + Send + 'static,
    {
        let total_ticks = delay.as_secs() / self.precision.as_secs();
        let mut cycles = [0u8; 3];
        let mut remaining = total_ticks;

        // 分层计算时间轮位置
        for (i, &divisor) in [60, 60, 24].iter().enumerate() {
            cycles[i] = (remaining / divisor as u64) as u8;
            remaining %= divisor as u64;
        }

        let task = ScheduledTask {
            execute_at: self.current_tick.load(Ordering::Relaxed) + total_ticks,
            task: Box::pin(f),
            cycles,
        };

        // 根据延迟时间选择对应层级
        let wheel_level = match total_ticks {
            0..=59 => 0,
            60..=3599 => 1,
            _ => 2,
        };

        let mut wheel = self.wheels[wheel_level].write().await;
        wheel.entry(task.execute_at).or_default().push_back(task);

        TaskHandle::new(/* 包含取消逻辑 */)
    }

    async fn start(&self) {
        let mut interval = interval(self.precision);
        loop {
            interval.tick().await;
            self.current_tick.fetch_add(1, Ordering::Relaxed);

            // 三级联动推进
            for level in 0..3 {
                self.process_wheel(level).await;
            }
        }
    }

    async fn process_wheel(&self, level: usize) {
        let current = self.current_tick.load(Ordering::Relaxed);
        let mut wheel = self.wheels[level].write().await;

        if let Some(tasks) = wheel.remove(&current) {
            for task in tasks {
                if task.cycles[level] > 0 {
                    // 降级到下层时间轮
                    let next_level = level + 1;
                    task.cycles[level] -= 1;
                    self.wheels[next_level]
                        .write()
                        .await
                        .entry(task.execute_at)
                        .or_default()
                        .push_back(task);
                } else {
                    // 提交到Tokio运行时
                    tokio::spawn(task.task);
                }
            }
        }
    }
}
